1 /* 2 Copyright: Marcelo S. N. Mancini (Hipreme|MrcSnm), 2018 - 2021 3 License: [https://creativecommons.org/licenses/by/4.0/|CC BY-4.0 License]. 4 Authors: Marcelo S. N. Mancini 5 6 Copyright Marcelo S. N. Mancini 2018 - 2021. 7 Distributed under the CC BY-4.0 License. 8 (See accompanying file LICENSE.txt or copy at 9 https://creativecommons.org/licenses/by/4.0/ 10 */ 11 module hip.systems.gameobject; 12 13 version(none): 14 version(HIPREME_DEBUG){import hip.error.handler;} 15 16 abstract class HipComponent 17 { 18 package bool hasStarted = false; 19 private HipGameObject _owner; 20 abstract void onStart(); 21 private void _onStart(HipGameObject go) 22 { 23 hasStarted = true; 24 _owner = go; 25 onStart(); 26 } 27 28 pragma(inline) 29 protected HipGameObject owner(){return _owner;} 30 31 pragma(inline, true) 32 public T getComponent(T)(){return _owner.getComponent!T;} 33 34 35 abstract void onRemove(); 36 abstract void update(float deltaTime); 37 } 38 39 class HipSpriteRendererComponent : HipComponent 40 { 41 import hip.graphics.g2d.sprite; 42 import hip.graphics.g2d.spritebatch; 43 44 HipSpriteBatch batch; 45 HipSprite sprite; 46 47 struct SpriteData 48 { 49 HipSpriteBatch batch; 50 HipSprite sprite; 51 } 52 53 void startWithData(void* data) 54 { 55 auto s = *cast(SpriteData*)data; 56 batch = s.batch; 57 sprite = s.sprite; 58 } 59 60 override void update(float delta) 61 { 62 batch.draw(sprite); 63 } 64 } 65 66 mixin template ComponentSpecialization(T) 67 { 68 mixin("T[] " ~ T.stringof~"Components;"); 69 70 HipComponent addComponent(T : HipComponent)() 71 { 72 T comp = new T(); 73 mixin(T~"Components~= comp;"); 74 return comp; 75 } 76 } 77 78 79 80 private __gshared ulong idCounter = 0; 81 82 class HipGameObject 83 { 84 ulong id; 85 string tag; 86 bool isActive = true; 87 88 public HipGameObject parent; 89 public HipGameObject[] children; 90 protected HipComponent[] components; 91 92 mixin ComponentSpecialization!(HipSpriteRendererComponent); 93 94 final public void addChild(HipGameObject go) 95 { 96 children~= go; 97 go.parent = this; 98 } 99 100 final public this(string tag) 101 { 102 id = ++idCounter; 103 this.tag = tag; 104 } 105 106 107 HipComponent addComponent(T : HipComponent)() 108 { 109 T comp = new T(); 110 components~= comp; 111 return comp; 112 } 113 T getComponent(T : HipComponent)() 114 { 115 foreach(c; components) 116 { 117 T ret = cast(T)c; 118 if(ret !is null) 119 return ret; 120 } 121 return null; 122 } 123 124 void removeComponent(T)() 125 { 126 foreach (ulong index, HipComponent c; components) 127 { 128 if(cast(T)c !is null) 129 { 130 components[index] = components[$-1]; 131 components.length--; 132 return; 133 } 134 } 135 version(HIPREME_DEBUG) 136 ErrorHandler.showErrorMessage("Removing component", tag~" has no component '"~T.stringof~"'"); 137 } 138 139 void update(float deltaTime) 140 { 141 if(!isActive) 142 return; 143 foreach(c; components) 144 { 145 if(!c.hasStarted) 146 c._onStart(this); 147 c.update(deltaTime); 148 } 149 foreach(child; children) 150 child.update(deltaTime); 151 } 152 }